﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using MODEL;

using IDAL;
using System.Data.Objects;

namespace DAL
{
    public class BaseDAL<T> : IBaseDAL<T> where T : class,new()
    {
        /// <summary>
        /// EF上下文对象
        /// </summary>
        DbContext db = new DBContextFactory().GetDbContext(typeof(T).Name);

        public BaseDAL()
        {
            //关闭 实体属性 的 验证检查
            db.Configuration.ValidateOnSaveEnabled = false;
        }

        public virtual void ADD(T model)
        {
            db.Set<T>().Add(model);
            //return db.SaveChanges();
        }

        public virtual void Del(T model)
        {
            db.Set<T>().Attach(model);
            db.Set<T>().Remove(model);
            //return db.SaveChanges();
        }

        public virtual void ModifyIsNullADD(T model, Expression<Func<T, bool>> whereLambda, bool isAll = false, params string[] ModifiedProNames)
        {
            List<T> listModifeding = db.Set<T>().Where(whereLambda).ToList();
            if (listModifeding != null && listModifeding.Count > 0)
            {
                if (isAll == true)
                {
                    Type t = typeof(T);
                    List<PropertyInfo> proInfo = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
                    List<string> ls = new List<string>();
                    proInfo.ForEach(p =>{
                        if (p.PropertyType.IsPrimitive==false)
                        {
                            ls.Add(p.Name);
                        }
                    });
                    ModifiedProNames = ls.ToArray();
                }

                Modify(model,whereLambda, ModifiedProNames);
            }
            else
            {
                
                ADD(model);
            }
        }

        public virtual void DelByWhere(Expression<Func<T, bool>> delwhere)
        {
            List<T> DeleList = db.Set<T>().Where(delwhere).ToList();//查询要删除的数据
            //将要删除的数据用删除方法添加到EF 容器中
            DeleList.ForEach(u => { db.Set<T>().Attach(u); db.Set<T>().Remove(u); });
            //return db.SaveChanges();
        }


        public virtual void Modify(T model, params string[] ProNames)
        {
            DbEntityEntry entry = db.Entry<T>(model);
            entry.State = System.Data.EntityState.Unchanged;
            foreach (string Name in ProNames)
            {
                entry.Property(Name).IsModified = true;
            }
            //return db.SaveChanges();
        }

        public virtual void Modify(T model, Expression<Func<T, bool>> whereLambda, params string[] ModifiedProNames)
        {
            List<T> listModifeding = db.Set<T>().Where(whereLambda).ToList();
            Type t = typeof(T);
            List<PropertyInfo> proInfo = t.GetProperties(BindingFlags.Instance | BindingFlags.Public).ToList();
            Dictionary<string, PropertyInfo> dictPros = new Dictionary<string, PropertyInfo>();

            proInfo.ForEach(p =>
                {
                    if (ModifiedProNames.Contains(p.Name))
                    {
                        dictPros.Add(p.Name, p);
                    }
                });

            foreach (string Name in ModifiedProNames)
            {
                if (dictPros.ContainsKey(Name))
                {
                    PropertyInfo PInfo = dictPros[Name];
                    object NewValue = PInfo.GetValue(model, null);
                    foreach (T us in listModifeding)
                    {
                        PInfo.SetValue(us, NewValue, null);
                    }
                }
            }
            //return db.SaveChanges();
        }


        public virtual List<T> GetListByWhere(Expression<Func<T, bool>> whereLambda)
        {
            return db.Set<T>().Where(whereLambda).ToList();
        }

        public virtual List<T> GetListByWhere<K>(Expression<Func<T, bool>> whereLambda, Expression<Func<T, K>> orderLambda, bool isAsc = true)
        { 
            if (isAsc)
            { 
                return db.Set<T>().Where(whereLambda).OrderBy(orderLambda).ToList();
            }
            else
            {
                return db.Set<T>().Where(whereLambda).OrderByDescending(orderLambda).ToList();
            } 
        }

         
        public virtual List<T> GetPageList<K>(int pageIndex, int pageSize, Expression<Func<T, bool>> whereLambda, Expression<Func<T, K>> orderLambda)
        {
            return db.Set<T>().Where(whereLambda).OrderBy(orderLambda).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
        }

        public virtual List<T> GetPageList<K>(int pageIndex, int pageSize, out int rowCount, Expression<Func<T, bool>> whereLambda, Expression<Func<T, K>> orderBy, bool isAsc = true)
        {
            if (isAsc)
            {
                IQueryable<T> IQuery = db.Set<T>().Where(whereLambda);
                rowCount = IQuery.Count();
                return IQuery.OrderBy(orderBy).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            }
            else
            {
                IQueryable<T> IQuery = db.Set<T>().Where(whereLambda);
                rowCount = IQuery.Count();
                return IQuery.OrderByDescending(orderBy).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); 
            }
        }
         
        public virtual int ExcuteSql(string strSql, params object[] paras)
        {
            return db.Database.ExecuteSqlCommand(strSql, paras);
        }
         
        public virtual List<T> ExecProcedure<T>(string functionName,params ObjectParameter[] parameter)
        {
          return ((IObjectContextAdapter)db).ObjectContext.ExecuteFunction<T>(functionName, parameter).ToList();
        }
    }
   
}
